
package com.gcloud.controller.storage.driver;

import com.gcloud.common.util.SystemUtil;
import com.gcloud.controller.storage.dao.VolumeDao;
import com.gcloud.controller.storage.entity.Snapshot;
import com.gcloud.controller.storage.entity.StoragePool;
import com.gcloud.controller.storage.entity.Volume;
import com.gcloud.controller.storage.model.CreateDiskResponse;
import com.gcloud.controller.storage.service.IVolumeService;
import com.gcloud.core.exception.GCloudException;
import com.gcloud.header.compute.enums.StorageType;
import com.gcloud.header.log.enums.LogType;
import com.gcloud.header.storage.StorageErrorCodes;
import com.gcloud.header.storage.enums.VolumeStatus;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class CephStorageDriver implements IStorageDriver {

    @Autowired
    private VolumeDao volumeDao;

    @Autowired
    private IVolumeService volumeService;

    @PostConstruct
    private void init() {

    }

    @Override
    public StorageType storageType() {
        return StorageType.CEPH;
    }

    @Override
    public void createStoragePool(String poolId, String poolName, String hostname, String taskId) throws GCloudException {
        String[] cmd = new String[] {"ceph", "--user", "gcloud", "osd", "pool", "create", poolName, "64", "64"};
        this.exec(cmd, StorageErrorCodes.FAILED_TO_CREATE_POOL);
    }

    @Override
    public void deleteStoragePool(String poolName) throws GCloudException {
        String[] cmd = new String[] {"ceph", "--user", "gcloud", "osd", "pool", "rm", poolName, poolName, "--yes-i-really-really-mean-it"};
        this.exec(cmd, StorageErrorCodes.FAILED_TO_DELETE_POOL);
    }

    @Override
    public CreateDiskResponse createVolume(String taskId, StoragePool pool, Volume volume) throws GCloudException {
        String[] cmd = new String[] {"rbd", "--user", "gcloud", "create", "--pool", volume.getPoolName(), "--image", volume.getProviderRefId(), "--size", volume.getSize() + "G"};
        this.exec(cmd, StorageErrorCodes.FAILED_TO_CREATE_VOLUME);
        this.volumeDao.updateVolumeStatus(volume.getId(), VolumeStatus.AVAILABLE);

        CreateDiskResponse response = new CreateDiskResponse();
        response.setLogType(LogType.SYNC);
        response.setDiskId(volume.getId());
        return response;
    }

    @Override
    public void deleteVolume(String taskId, StoragePool pool, Volume volume) throws GCloudException {
        String[] cmd = new String[] {"rbd", "--user", "gcloud", "rm", "--no-progress", "--pool", volume.getPoolName(), "--image", volume.getProviderRefId()};
        this.exec(cmd, StorageErrorCodes.FAILED_TO_DELETE_VOLUME);
        this.volumeService.handleDeleteVolumeSuccess(volume.getId());
    }

    @Override
    public void resizeVolume(String taskId, StoragePool pool, Volume volume, int newSize) throws GCloudException {
        String[] cmd = new String[] {"rbd", "--user", "gcloud", "resize", "--no-progress", "--pool", volume.getPoolName(), "--image", volume.getProviderRefId(), "--size",
                newSize + "G"};
        this.exec(cmd, StorageErrorCodes.FAILED_TO_RESIZE_VOLUME);
        this.volumeService.handleResizeVolumeSuccess(volume.getId(), newSize);
    }

    @Override
    public void createSnapshot(Volume volume, String snapshotRefId) throws GCloudException {
        String[] cmd = new String[] {"rbd", "--user", "gcloud", "snap", "create", "--pool", volume.getPoolName(), "--image", volume.getProviderRefId(), "--snap", snapshotRefId};
        this.exec(cmd, StorageErrorCodes.FAILED_TO_CREATE_SNAP);
    }

    @Override
    public void deleteSnapshot(Volume volume, Snapshot snapshot) throws GCloudException {
        String[] cmd = new String[] {"rbd", "--user", "gcloud", "snap", "rm", "--no-progress", "--pool", snapshot.getPoolName(), "--image", volume.getProviderRefId(), "--snap",
                snapshot.getProviderRefId()};
        this.exec(cmd, StorageErrorCodes.FAILED_TO_DELETE_SNAP);
    }

    @Override
    public void resetSnapshot(Volume volume, Snapshot snapshot) throws GCloudException {
        String[] cmd = new String[] {"rbd", "--user", "gcloud", "snap", "rollback", "--no-progress", "--pool", snapshot.getPoolName(), "--image", volume.getProviderRefId(),
                "--snap", snapshot.getId()};
        this.exec(cmd, StorageErrorCodes.FAILED_TO_RESET_SNAP);
    }

    private void exec(String[] cmd, String errorCode) throws GCloudException {
        int res;
        try {
            res = SystemUtil.runAndGetCode(cmd);
        }
        catch (Exception e) {
            throw new GCloudException(errorCode);
        }
        if (res != 0) {
            throw new GCloudException(errorCode);
        }
    }

}
